Hej med jer! (Danish for 'Gidda!)

This is a general letter, I mail to these people: George Taylor,
Andreas Boose, David Gahris and Marko Makela. I'll reply personally
to your letters soon. Maybe we should set up a mailing-list for the
examination of the grubby details of the c64? Besides the SID, work
is being done on the VIC-II and maybe other things. I don't have the
facilities needed for such a thing, but maybe Craig Bruce can help in
this regard?

I have continued research regarding the frequency/waveform mapping
for the triangle and sawtooth waveform. I will look into the noise
waveform soon, but here follows my results (which I'll incorporate in
my general SID-document as well as any comments) based on recording
the triangle waveform:

Data recorded on the triangle waveform ($10)
--------------------------------------------

The data are recorded using a REU. The recording is done like this:

        ;* Program 1 *

        ;Turn off screen and sprites

        ...

        ;Set frequency of voice 3

        LDA #<freq
        LDX #>freq
        STA $D40E
        STX $D40F

        ;Reset waveform

        LDA #$08        ;Set test bit
        STA $D412

        ;Setup REU to sample register $D41B for $10000 cycles

        ...

        ;Start recording

        LDA #$10        ;Waveform: Triangle
        LDX #%1001000   ;REU-command: Start transfer
        STA $D412       ;Start waveform
        STX $DF01       ;Start transfer

        ...

Furthermore, a construct like this is used to get a value from the
waveform as fast as possible (via software) from the SID:

        ;* Program 2 *

        ...

        LDA #$10
        STA $D412       ;Start waveform
        LDA $D41B       ;Record early value
        STA Haps        ;Save value

        ...

The table below summarizes the recordings (all values in hex):

Frequency  Haps REU

8000       04   05 06 07 ... FD FE FF FF FE ... 01 00 00 01 ...
4000       02   02 03 03 04 04 ...
2000       01   01 01 01 02 02 02 02 03 03 03 03 04 ...
1000       00   00 00 00 01 01 01 01 01 01 01 01 01 02 ...
FFFF       07   09 0B 0D 0F 11 13 15 17
DEAD       06   08 0A 0C 0D 0F 11 13 14 16 18 1A 1B 1D 1F 21 22 24 26
                28 29 2B 2D 2E 30 32 34 35 37 39 3B 3C 3E 40 42 43 45
                47 49 4A 4C 4E 50 51 53 55 56 58 5A 5C 5D 5F 61 63 64

Legend:
Frequency is the value stored to $D40E and $D40F.
Haps is the value of the Haps variable from program 2.
REU is the data collected with the REU after running program 1.

Conclusion: The triangle waveform starts with value $00 and goes to
$ff linearly. Then it goes from $ff to $00 linearly.

(As a sidenote, I'll mention that the data for the sawtooth
waveform at frequency $8000 is Haps= 02, REU= 02 03 03 04 04 ...
FE FE FF FF 00 00 01 01 ...)

The Haps variable is the value of the waveform on one cycle earlier
than the REU starts recording.

Further data used to investigate the frequency/waveform mapping:

Frequency
      Haps+REU, Number of this*value

0001  7FFC*00 8000*01 8000*02 ...
0002  3FFC*00 4000*01 4000*02 ...
0003  2AA7*00 2AAB*01 2AAA*02 2AAB*03
0004  1FFC*00 2000*01 2000*02 ...
0005  1996*00 199A*01 1999*02 199A*03 1999*04
0006  1552*00 1555*01 1555*02 1556*03 1555*04 1555*05 1556*06
0007  1245*00 1249*01 1249*02 1249*03 1249*04 1249*05 1249*06 124A*07
      1249*08
0008  0FFC*00 1000*01 1000*02 ...
0009  0E35*00 0E39*01 0E39*02
000A  0CC9*00 0CCD*01
000B  0B9F*00

Legend:
Frequency is the value stored to $D40E and $D40F.
Haps+REU is the contents of the Haps variable from program 2 and the
contents of the REU after running program 1. The format is number of
times of repeation * value. I.e. 7FFC*00 means that the value "00"
repeated $7FFC times after each other in the data. 0003*FE 0004*DE
would mean this sequence of data was recorded: FE FE FE DE DE DE DE.
The first FE would come from the variable Haps, while the rest would
be obtained with the REU.

Conclusion: We know that with the STA $D412; LDA $D41B construct, .a
contains the value of the waveform after 4 cycles. This is consistens
with the observation that the number of times the value $00 appear
generally is 4 lower than the number of times the other values appear.

The overall behaviour can thus be simulated with this C-program:

void Triangle(long Frequency) {
  long Cycle; /* Count of Phi2 cycles */

  long Delay= 0x8000;
  long Counter= 0; /* Initial value is 0 */

  for (Cycle=0; ;Cycle= Cycle+1) {

    /* Build waveform: Triangle */
    if (Counter < 256)
      Waveform[cycle]= Counter;
    else
      Waveform[cycle]= 511- Counter;

    /*
      For the sawtooth waveform, use:

      Waveform[Cycle]= Counter / 2;
    */

    /* Handle frequency-function */
    Delay = Delay- Frequency;

    /* Frequency overflow? */
    while (Delay <=0 ) do {
      /* For frequencies above $8000, this will be executed twice */

      Delay = Delay + 0x8000;

      /* Calculate new value for waveform */
      Counter= (Counter+1) % 512; /* Keep in range 0..511 */
    }
  }
}

I haven't checked this, since I don't have a C-compiler handy, so
maybe you could check it for me against the data in the above tables?

The above program (when checked) is only capable of reproducing the
output of register $1B. We can't be sure that the true output of pin
27 of the SID is the same. In this respect, there are two issues:

Is the output digital and 8 bit?
Is the output aligned to the Phi2 clock?

Is the output digital and 8 bit?
--------------------------------

People have used oscilloscopes and concluded that this is the output
is digital and probably 8 bit. This can also be checked with this
program, if you have decent audio-equipment:

        jsr $e544       ;Clear screen

        ldx #0
        stx $d021       ;Background color black
        stx $d020       ;Border black
                        ;(The black color reduces noise with my equipment)

        lda #11         ;As of request from Andreas with kernal R2 :-)
col     sta $d800,x     ;Character color dark grey
        inx
        bne col

        lda #$01        ;Frequency 1
        sta $d40e
        lda #$00
        sta $d40f

        lda #$00        ;ADSR:00F0
        sta $d412
        lda #$f0
        sta $d413

        lda #$81        ;Waveform: Random, changes rarely.
                        ;Change for other waveforms
        sta $d412

        lda #$0f        ;Max volume: $f
        sta $d418

        ldx $d41b
loop1   stx temp

loop2   ldx $d41b
        cpx temp
        bne loop2

        lda $0400,x     ;Display when value changes
        eor #$80
        sta $0400,x
        jmp loop1

temp    .byte $00

Turn up the volume of the TV-set and you can hear the "ticks" when
the waveform changes every few seconds. If the ticks happen in
alignment with the changes on the screen, the output is digital and 8
bit.

You can also try other waveforms (substitute the lda #$81 with lda
#$11 for triangle or lda #$21 for sawtooth. Pulse ($41) requires
definition of the pulse width in $d410 and $d411), but these are all
much faster and/or the changes in the waveform are small, so it is
not as easy to hear the distinct ticks.

Is the output aligned to the Phi2 clock?
----------------------------------------

This is an open question as of now (23 Mar 1995 :-). My feeling is
that the output is aligned, but this is only a feeling based on the
fact that, all, the SID has available to synchronize with, is the
Phi2 feed.

I believe examination of this requires an oscilloscope, which I have
no access to. What should be done is to display the Phi2 clock along
with the pin 27 output with a triangle waveform at frequency $ffff
(Just modify the above program to use frequency $ffff and triangle
waveform). If the waveform change only once every Phi2 cycle, the
output is Phi2 aligned and thus "skipping values". If not, the
waveform would change twice every phi2 cycle and thus display all 256
values. If this is the case, I have further studies to be done to
clarify whether the output is happening in a discrete partition of
the Phi2 cycle.

Observation
-----------

If you record the data of the waveform with a structure like this:

        ...

        lda #$08        ;Reset waveform: Test bit is 1.
        sta $d412

        lda #$00        ;Frequency $8000
        sta $d40e
        lda #$80
        sta $d40f

        ...

        ldy #$00        ;Clear test bit
        lda #$10        ;Waveform triangle
        ldx #$90        ;REU command
        sty $d412       ;The difference!
        sta $d412
        stx $df01

the recorded data are all 4 cycles behind! I.e. the first value in
the REU data is not $05, but $09. The similar thing happens if you
use the capture in program 2: Instead of getting $04, you get $08.
The 4 cycle delay is the time it, the sta $d412 takes.

If you change the ldy #$00 (test bit=0) to ldy #$08 (test bit=1), the
effect disappears, so the conclusion is:

The triangle counter counts all the time, whether or not the waveform
is activated. The counter is held reset to 0 when the test bit is 1
(supposedly), and as soon as the test bit is 0, the counter starts
counting. Another explanation, with the same result, is that the
counter is reset on falling edge of the test bit.

I have not examined whether this is the case for the sawtooth and the
pulse waveforms, but my bet is, this is the case.

Until next time (and we have still lots of things to clarify :-),

--
Asger Alstrup, diku0748@diku.dk (or bastard@diku.dk)

